import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Upload as AntdUpload } from 'antd';
import axios from 'axios';

import styles from './style.scss';
import ImageGallery from '../ImageGallery';
import request from './request';

export default class SinglePictureUpload extends Component {

    static propTypes = {
        uploadedFile: PropTypes.string,
        onChange: PropTypes.func,
        onDelete: PropTypes.func,
        onBeforeUploadAbort: PropTypes.func,
        singlePictureUploadWrap: PropTypes.string,
    };

    static defaultProps = {
        onChange: () => undefined,
        onDelete: () => undefined,
        onBeforeUploadAbort: () => undefined,
    };

    constructor(props) {
        super(props);
        this.state = {
            isUploading: false,
            isMouseOver: false,
            previewImage: '',
            error: null,
        };

        this.tokenKey = `file_upload_token${props.accept}`;
        this.targetKey = 'file_upload_url';
    }

    beforeUpload = (file, fileList) => {
        const { accept, maxSize, onBeforeUploadAbort } = this.props;
        const { name, size } = file;
        return new Promise(async (resolve, reject) => {
            if (name.length > 100) {
                onBeforeUploadAbort(3, file, fileList);
                this.setState({
                    error: '图片名称不能超过100个字符'
                });
                return reject();
            }
            if (accept) {
                let arrAccept = accept.toLowerCase().split(',');
                const ext = name.substr(name.lastIndexOf('.')).toLowerCase();
                if (arrAccept.indexOf(ext) === -1) {
                    onBeforeUploadAbort(1, file, fileList);
                    this.setState({
                        error: '不支持上传该类型的图片'
                    });
                    return reject();
                }
            }
            if (maxSize > 0 && size > maxSize) {
                onBeforeUploadAbort(2, file, fileList);
                let humanReadableMaxSize;
                if (maxSize >= 1 << 20) {
                    humanReadableMaxSize = (maxSize >> 20) + 'M';
                } else if (maxSize >= 1 << 10) {
                    humanReadableMaxSize = (maxSize >> 10) + 'K';
                } else {
                    humanReadableMaxSize = maxSize + 'B';
                }
                this.setState({
                    error: `图片大小不能超过${humanReadableMaxSize}`
                });
                return reject();
            }
            let token = sessionStorage.getItem(this.tokenKey);

            let uploadUrl = sessionStorage.getItem(this.targetKey);
            if (!token || !uploadUrl) {
                const res = await axios.get('/upload-token', {
                    headers: {
                        'X-Requested-With': 'XMLHttpRequest',
                        'Cache-Control': 'no-cache',
                        'Pragma': 'no-cache',
                    }
                }).then(res => res.data).catch(err => null);
                if (res && res.data) {
                    token = res.data.token;
                    uploadUrl = res.data.host + '/api/upload';
                }
                if (!token) {
                    this.setState({
                        error: '上传失败，获取资源服务器校验信息错误'
                    });
                    return reject();
                }
                sessionStorage.setItem(this.tokenKey, token);
                sessionStorage.setItem(this.targetKey, uploadUrl);
            }
            if (this.state.error) {
                this.setState({
                    error: null
                });
            }
            resolve();
        });

    };

    onChange = info => {
        const { onChange } = this.props;
        const file = info.file;
        if (!file) {
            return;
        }
        if (file.status === 'uploading' && !this.state.isUploading) {
            this.setState({
                isUploading: true,
                error: null,
            });
        } else if (file.status === 'done') {
            this.setState({
                isUploading: false,
                error: null
            });
        } else if (file.status === 'error') {
            this.setState({
                isUploading: false,
                error: file.error && file.error.message || '上传失败'
            });
            sessionStorage.removeItem(this.tokenKey);
            sessionStorage.removeItem(this.targetKey);
        }
        onChange(info);
    };

    onPreviewBtnClick = evt => {
        const { uploadedFile } = this.props;
        this.setState({
            previewImage: uploadedFile,
        });
    };

    onPreviewCancel = evt => {
        this.setState({
            previewImage: null
        });
    };

    onUploadedMouseEnter = evt => {
        this.setState({
            isMouseOver: true
        });
    };
    onUploadedMouseLeave = evt => {
        this.setState({
            isMouseOver: false
        });
    };

    onDeleteBtnClick = evt => {
        const { onDelete } = this.props;
        onDelete(evt);
    };

    processRequestData = file => {
        return {
            key: 'file',
            token: sessionStorage.getItem(this.tokenKey),
            redirect: 'none',
            file: file
        };
    };

    render() {
        const { uploadedFile, accept, wrapperClass, style } = this.props;
        const { isUploading, isMouseOver, previewImage, error } = this.state;
        const uploadBtn = isUploading ? '上传中' : (
            <div className={styles.btnImageUpload}>
                上传图片
            </div>
        );
        let cls = styles.singlePictureUploadWrap;
        if (wrapperClass) {
            cls += ' ' + wrapperClass;
        }

        return (
            <div className={cls} style={style}>
                <div className={styles.singlePictureUpload}>
                    {
                        uploadedFile ?
                            <div className={styles.spuUploaded} onMouseEnter={this.onUploadedMouseEnter} onMouseLeave={this.onUploadedMouseLeave}>
                                <img src={uploadedFile} alt="已上传图片" />
                                {
                                    isMouseOver ?
                                        <div className={styles.spuUploadedOperation}>
                                            <a className={styles.btnImagePreview} onClick={this.onPreviewBtnClick}></a>
                                            <a className={styles.btnImageDelete} onClick={this.onDeleteBtnClick}></a>
                                            { /*
                            <a className={styles.btnImageDownload}></a>
                            */ }
                                        </div> :
                                        null
                                }
                            </div> :
                            <div className={styles.spuUploader}>
                                <AntdUpload
                                    listType="picture-card"
                                    beforeUpload={this.beforeUpload}
                                    customRequest={request}
                                    showUploadList={false}
                                    onChange={this.onChange}
                                    accept={accept}
                                    disabled={isUploading}
                                    data={this.processRequestData}
                                >
                                    {uploadBtn}
                                </AntdUpload>
                                <div className={styles.spuErrMsg}>{error}</div>
                            </div>
                    }
                    {
                        previewImage ?
                            <ImageGallery
                                fixed
                                dataSource={[previewImage]}
                                onCancel={this.onPreviewCancel}
                            /> : null
                    }
                </div>
                <div className={styles.spuDescribe}>
                    {this.props.describe}
                </div>
            </div>
        );
    }
}
